package com.tianfei.crowd.controller;

import com.tianfei.crowd.api.MySQLRemoteService;
import com.tianfei.crowd.api.RedisRemoteService;
import com.tianfei.crowd.config.ShortMessageProperties;
import com.tianfei.crowd.constant.CrowdConstants;
import com.tianfei.crowd.entity.po.MemberPO;
import com.tianfei.crowd.entity.vo.MemberLoginVO;
import com.tianfei.crowd.entity.vo.MemberVO;
import com.tianfei.crowd.utils.CrowdUtil;
import com.tianfei.crowd.utils.ResultEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;


import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 会员 的controller
 *
 * @author: Herz
 * @date: 2021/7/30 18:34
 */
@Controller
public class MemberController {

    @Autowired
    private ShortMessageProperties shortMessageProperties;

    @Autowired
    private RedisRemoteService redisRemoteService;

    @Autowired
    private MySQLRemoteService mySQLRemoteService;


    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session) {

        // 清空 session 域的登录信息
        session.invalidate();

        return "redirect:http://localhost/";
    }


    @RequestMapping("/auth/do/member/login")
    public String doLogin(
            @RequestParam("loginacct") String loginacct,
            @RequestParam("userpswd") String userpswd,
            ModelMap modelMap,
            HttpSession session) {

        // 1、判断当前账号是否正确
        ResultEntity<MemberPO> loginResultEntity = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginacct);

        // 查询失败
        if (ResultEntity.FAILED.equals(loginResultEntity.getResult())) {
            modelMap.addAttribute(CrowdConstants.ATTR_NAME_MESSAGE, loginResultEntity.getMessage());

            return "member-login";
        }

        MemberPO memberPO = loginResultEntity.getData();
        // 查询成功，但该会员用户不存在
        if (memberPO == null) {
            modelMap.addAttribute(CrowdConstants.ATTR_NAME_MESSAGE, CrowdConstants.MESSAGE_LOGIN_FAILED);

            return "member-login";
        }

        // 2、查询成功，判断密码是否正确
        String MySQLUserPwd = memberPO.getUserpswd();

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        boolean matches = passwordEncoder.matches(userpswd, MySQLUserPwd);

        if (!matches) {
            modelMap.addAttribute(CrowdConstants.ATTR_NAME_MESSAGE, CrowdConstants.MESSAGE_LOGIN_FAILED);

            return "member-login";
        }

        // 3、创建 MemberLoginVO 对象存入 Session 域
        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(), memberPO.getUsername(), memberPO.getEmail());

        session.setAttribute(CrowdConstants.MESSAGE_ATTR_MEMBER, memberLoginVO);

        return "redirect:http://localhost/auth/member/to/center/page";
    }


    @RequestMapping("/auth/do/member/register")
    public String doRegister(MemberVO memberVO, ModelMap modelMap) {

        // 1、判断当前注册账号是否存在
        String loginacct = memberVO.getLoginacct();

        if (loginacct == null || loginacct.equals("") || loginacct.length() == 0){
            modelMap.addAttribute(CrowdConstants.ATTR_NAME_MESSAGE, CrowdConstants.MESSAGE_STRING_ILLEGAL);

            return "member-register";
        }


        ResultEntity<MemberPO> getMemberResultEntity = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginacct);

        if (getMemberResultEntity.getData() != null) {
            modelMap.addAttribute(CrowdConstants.ATTR_NAME_MESSAGE, CrowdConstants.MESSAGE_ALREADY_ACCT);

            return "member-register";
        }


        // 2、获取用户输入的手机号
        String phoneNum = memberVO.getPhoneNum();
        // 3、拼 redis 中要查找的 key
        String key = CrowdConstants.REDIS_CODE_PREFIX + phoneNum;

        // 4、根据 key 在 redis 中查找验证码 value
        ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote(key);

        String result = resultEntity.getResult();
        // 5、判断查询是否有效
        if (ResultEntity.FAILED.equals(result)) {

            modelMap.addAttribute(CrowdConstants.ATTR_NAME_MESSAGE, resultEntity.getMessage());

            return "member-register";

        }

        String redisCode = resultEntity.getData();

        if (redisCode == null) {
            // 手机号输入错误
            modelMap.addAttribute(CrowdConstants.ATTR_NAME_MESSAGE, CrowdConstants.MESSAGE_CODE_UNEXIST);

            return "member-register";
        }

        // 6、如果能在redis查询到value，则比较表单验证码 和 该redis 中得验证码是否一致


        String formCode = memberVO.getCode();

        if (!Objects.equals(formCode, redisCode)) {
            modelMap.addAttribute(CrowdConstants.ATTR_NAME_MESSAGE, CrowdConstants.MESSAGE_INPUT_CODE_ERROR);

            return "member-register";
        }

        // 7、如果验证码一致，则删除
        redisRemoteService.removeRedisKeyRemote(key);

        // 8、执行密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        // 获取表单密码
        String userpswd = memberVO.getUserpswd();

        String encodePwd = passwordEncoder.encode(userpswd);

        memberVO.setUserpswd(encodePwd);

        // 9、执行保存
        // ① 创建一个空的 MemberPO 对象
        MemberPO memberPO = new MemberPO();

        // ② 复制属性
        BeanUtils.copyProperties(memberVO, memberPO);

        // ③ 保存
        mySQLRemoteService.saveMemberRemote(memberPO);

        // 使用重定向，避免浏览器刷新重复提交表单
        return "redirect:/auth/member/to/login/page";

    }


    @ResponseBody
    @RequestMapping("/auth/member/send/short/message")
    public ResultEntity<String> sendShortMessage(@RequestParam("phoneNum") String phoneNum) {

        // 1、发送验证码到手机
        ResultEntity<String> sendCodeResultEntity = CrowdUtil.sendCodeByShortMessage(
                shortMessageProperties.getHost(),
                shortMessageProperties.getPath(),
                shortMessageProperties.getMethod(),
                shortMessageProperties.getAppCode(),
                phoneNum,
                shortMessageProperties.getSmsSignId(),
                shortMessageProperties.getTemplateId());

        // 2、判断你短信发送结果
        if (ResultEntity.SUCCESS.equals(sendCodeResultEntity.getResult())) {

            // 3、短信发送成功，将验证码存到 Redis 里面
            // ① 从上一步的结果中获取发送的验证码
            String code = sendCodeResultEntity.getData();

            // ② 设置存在 Redis 里的键
            String key = CrowdConstants.REDIS_CODE_PREFIX + phoneNum;

            // ③ 执行保存验证码
            ResultEntity<String> saveCodeResultEntity = redisRemoteService.setRedisKeyValueRemoteWithTimeOut(key, code, 5, TimeUnit.MINUTES);

            // ④ 判断验证码是否保存成功
            if (ResultEntity.SUCCESS.equals(saveCodeResultEntity.getResult())) {

                // 验证码保存成功
                return ResultEntity.successWithOutData();
            } else {
                // 验证码保存失败
                return saveCodeResultEntity;
            }
        } else {
            // 4、短信发送失败
            return sendCodeResultEntity;
        }
    }
}
